package com.example.demo.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.example.demo.core.Result;
import com.example.demo.domain.online.HouseInfoData;
import com.example.demo.entity.AdminUser;
import com.example.demo.entity.Online;
import com.example.demo.entity.ResourceFile;
import com.example.demo.exception.UnknownException;
import com.example.demo.pojo.request.CronTriggerCreateRequest;
import com.example.demo.pojo.response.QuartzCronTriggerResponse;
import com.example.demo.pojo.response.QuartzJobDetailResponse;
import com.example.demo.service.*;
import com.example.demo.unitls.TokenUtils;
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


/**
 * 为了方便快速测试一些功能这里定义一个不需要认证就可以访问的控制器
 *
 * @author 叮当猫的百宝箱
 * @since 1.0
 */
@Slf4j
@RequestMapping("/developer")
@RestController
@RequiredArgsConstructor
public class NotAuthController {

    private final ResourceFileService resourceService;

    private final AdminUserService adminUserService;

    private final TokenUtils tokenUtils;

    private final OnlineService onlineService;
    private final QuartzSchedulerService quartzSchedulerService;

    private final EmailService mailService;

    @Value("${erp.contract-template.dir}")
    private String contractTemplateDir;

    public static class DemoData {

        @ExcelProperty(value = "姓名", index = 0)
        private String name;

        @ExcelProperty(value = "年龄", index = 1)
        private Integer age;

        @ExcelProperty(value = "生日", index = 2)
        @ColumnWidth(50)
        private LocalDateTime birthday;

        public DemoData(String name, Integer age, LocalDateTime birthday) {
            this.name = name;
            this.age = age;
            this.birthday = birthday;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }

        public LocalDateTime getBirthday() {
            return birthday;
        }

        public void setBirthday(LocalDateTime birthday) {
            this.birthday = birthday;
        }
    }

    @PostMapping("/excel")
    public void export(HttpServletResponse response) throws IOException {

        List<DemoData> data = new ArrayList<>();
        data.add(new DemoData("张三", 20, LocalDateTime.now()));
        data.add(new DemoData("李四", 25, LocalDateTime.now()));

        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");
        String filename = URLEncoder.encode("demo.xlsx", "UTF-8");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename);
        ExcelWriterSheetBuilder excelWriterBuilder = EasyExcel.write(response.getOutputStream(), DemoData.class).sheet("Sheet1");


        excelWriterBuilder.doWrite(data);
    }

    @PostMapping("/contract")
    public Result<Online> contract() {
        Online onlineById = onlineService.getOnlineById(1L);
        return Result.ok(onlineById);
    }

    @PostMapping("/returnContract")
    public Result<Void> returnContract() {
        onlineService.applyTermination(
                1L,
                "0309",
                "皓月坊",
                "30175",
                "HYDR20249190",
                null
        );
        return Result.ok();
    }


    @PostMapping("/confirmTermination")
    public Result<Void> confirmTermination() {
        HouseInfoData houseInfo = new HouseInfoData();
        houseInfo.setArea("37.89");
        houseInfo.setCategory("公租房");
        houseInfo.setBuildingFloor("12");
        houseInfo.setBuildingNo("8");
        houseInfo.setRoomType("1");
        houseInfo.setRoomNo("1203");
        houseInfo.setActualRent("3824.00");
        houseInfo.setMonthlyRent("3824.00");
        onlineService.confirmTermination(
                1L,
                "0309",
                "皓月坊",
                "30175",
                "HYDR20249190",
                null,
                "2024-04-30",
                houseInfo

        );
        return Result.ok();
    }

    @GetMapping("/scheduler")
    public Result<List<QuartzJobDetailResponse>> scheduler() {
        List<QuartzJobDetailResponse> allJobDetails = quartzSchedulerService.getAllJobDetails();
        return Result.ok(allJobDetails);
    }

    @GetMapping("/triggers")
    public Result<List<QuartzCronTriggerResponse>> triggers() {
        List<QuartzCronTriggerResponse> allTriggers = quartzSchedulerService.getAllTriggers();
        return Result.ok(allTriggers);
    }


    @PostMapping("/pauseTrigger/{triggerName}/{triggerGroup}")
    public Result<Void> pauseTrigger(@PathVariable String triggerName, @PathVariable String triggerGroup) {
        quartzSchedulerService.pauseTrigger(triggerName, triggerGroup);
        return Result.ok();
    }

    @PostMapping("/resumeTrigger/{triggerName}/{triggerGroup}")
    public Result<Void> resumeTrigger(@PathVariable String triggerName, @PathVariable String triggerGroup) {
        quartzSchedulerService.resumeTrigger(triggerName, triggerGroup);
        return Result.ok();
    }


    @PostMapping("/updateCronTrigger/{triggerName}/{triggerGroup}")
    public Result<Void> updateCronTrigger(@PathVariable String triggerName, @PathVariable String triggerGroup, String newCronExpression) {
        quartzSchedulerService.updateCronTrigger(triggerName, triggerGroup, newCronExpression);
        return Result.ok();
    }

    @PostMapping("/createTrigger")
    public Result<Void> createTrigger(@Validated @RequestBody CronTriggerCreateRequest request) {
        quartzSchedulerService.createCronTrigger(request);
        return Result.ok();
    }

    @PostMapping("/sendEmail")
    public Result<Void> sendEmail() {
        mailService.sendInvoiceDownloadEmail("xufree888@gmail.com");
        return Result.ok();
    }

    @PostMapping("/me")
    public Result<UserDetails> me() {
        UserDetails userDetails = tokenUtils.getUserDetailsByContextHolder();
        return Result.ok(userDetails);
    }

    @PostMapping("/upload")
    public Result<ResourceFile> upload(MultipartFile file) {
        ResourceFile resource = resourceService.uploadImage(file);
        return Result.ok(resource);
    }

    @PostMapping("/addUser")
    public void addUser(@RequestBody AdminUser adminUser) {
        adminUserService.createAdminUser(adminUser);
    }


    /**
     * PDF 模版套打
     *
     * @throws IOException
     */
    @GetMapping("/print")
    public void print() throws IOException {
        String template = "/Users/xubo/Desktop/template.pdf";
        String dest = "/Users/xubo/Desktop/dest66";
        String uuid = UUID.randomUUID().toString();
        dest = dest + uuid + ".pdf";

        String fontPath = "/Users/xubo/Desktop/Fonts/simsun.ttc,0";
        // String imagePath = "/Users/xubo/Desktop/1.png";

        PdfDocument pdfDocument = new PdfDocument(new PdfReader(template), new PdfWriter(dest));
        PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, false);
        PdfFont font = PdfFontFactory.createFont(fontPath);
        DeviceRgb color = new DeviceRgb(0, 0, 0);

        Map<String, String> map = new HashMap<>();
        map.put("address", "上海市闵行区莲花南路1288");
        map.put("rent", "3000");
        map.put("other", "其他");
        map.put("check", "Yes");

        for (Map.Entry<String, String> entry : map.entrySet()) {
            PdfFormField pdfFormField = form.getFormFields().get(entry.getKey());
            if (pdfFormField != null) {
                pdfFormField.setValue(entry.getValue())
                        .setColor(color)
                        .setFont(font)
                        .setFontSize(14);
            }

        }

//        PdfFormField field = form.getField("image");
//        List<PdfWidgetAnnotation> widgets = field.getWidgets();
//        PdfWidgetAnnotation pdfWidgetAnnotation = widgets.get(0);
//
//        float x1 = pdfWidgetAnnotation.getRectangle().getAsNumber(0).floatValue();
//        float y1 = pdfWidgetAnnotation.getRectangle().getAsNumber(1).floatValue();
//        float x2 = pdfWidgetAnnotation.getRectangle().getAsNumber(2).floatValue();
//        float y2 = pdfWidgetAnnotation.getRectangle().getAsNumber(3).floatValue();
//
//        float fieldWidth = x2 - x1;
//        float fieldHeight = y2 - y1;
//
//        Image img = new Image(ImageDataFactory.create(imagePath));
//        Image image = img.scaleToFit(fieldWidth, fieldHeight);
//        float scaledWidth = image.getImageScaledWidth();
//        float scaledHeight = image.getImageScaledHeight();
//
//
//        float centerX = x1 + (fieldWidth / 2) - (scaledWidth / 2);
//        float centerY = y1 + (fieldHeight / 2) - (scaledHeight / 2);
//
//        img.setFixedPosition(centerX, centerY);
//
//        Document document = new Document(pdfDocument);
//        document.add(img);

        // 清楚表单作用域
        form.flattenFields();

//        document.close();
        pdfDocument.close();
    }


    @GetMapping("/getPdfField")
    public void getPdfTemplateAllField() {
        // PDF 模版的路径
        String template = "/Users/xubo/Desktop/template.pdf";

        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String fileName = dateTimeFormatter.format(now);

        File dir = new File(contractTemplateDir);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                throw new RuntimeException("初始化合同模版目录失败");
            }
        }
        log.info("Resource upload path initialized: {}", dir);
        File templateFile = new File(dir, fileName + ".pdf");

        try {
            PdfDocument pdfDocument = new PdfDocument(new PdfReader(template), new PdfWriter(templateFile));

            // 模版文件中的表单
            PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDocument, false);


            // TODO 这里先定义一个数组,后面可以通过策略模式来填充不同的变量
            Map<String, String> map = new HashMap<>(100);
            map.put("qualification_number", "202417100003042");
            map.put("contract_number", "WY20240060");
            map.put("company_name", "上海懋乐建筑装饰有限公司");
            map.put("name", "方向明");
            map.put("address", "上海市杨浦区顺平路1122弄9号201室");

            StringBuilder node = new StringBuilder();
            for (int i = 0; i < 10; i++) {
                node.append("减肥属于以减少人体过度的脂肪、体重为目的的行为方式。适度减重可降低患肥胖症的风险，也可提高有肥胖并发症的患者的健康水平。\n");
            }
            map.put("node", node.toString());

            log.debug("node:{}", node);

            // 遍历模版PDF表单,得到表单包含的所有列
            Map<String, PdfFormField> formFields = form.getFormFields();
            Set<String> fieldName = formFields.keySet();
            // 填充PDF模版中的表单项
            for (String key : fieldName) {
                log.debug("key:{}", key);

                // 检查这个表单字段是否需要填充
                String value = map.get(key);
                if (value != null) {
                    PdfFormField formField = formFields.get(key);
                    // 填充这个表单字段
                    formField.setValue(value).setColor(DeviceRgb.BLACK).setFontSize(10);
                }
            }

            // 清楚表单作用域
            form.flattenFields();
            pdfDocument.close();

        } catch (IOException e) {
            throw new UnknownException(e.getMessage());
        }

    }


}
